using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;



namespace WindowsGameInput
{
	public struct InputState
	{
		public bool cameraYawLeft;
		public bool cameraYawRight;
		public bool cameraPitchUp;
		public bool cameraPitchDown;
		public bool cameraRollLeft;
		public bool cameraRollRight;
		public bool cameraMoveForward;
		public bool cameraMoveBackward;
		public bool cameraMoveZForward;
		public bool cameraMoveZBackward;
		public bool playerMoveForward;
		public bool playerMoveBackward;
		public bool playerRotateLeft;
		public bool playerRotateRight;
		public bool playerShoot;

		public bool mouseLButtonPressed;
		public bool mouseLButtonReleased;
		public bool mouseRButtonPressed;
		public bool mouseRButtonReleased;
		public int mouseX;
		public int mouseY;
	}

	public interface IInputEventService
	{
		event Action ToggleHUD;
		event Action Quit;
	}



	public class InputHandler : Microsoft.Xna.Framework.GameComponent, IInputEventService
	{
		KeyboardState previousKeyboardState = new KeyboardState();
		MouseState previousMouseState = new MouseState();

		private static InputState inputState;

		public event Action ToggleHUD;
		public event Action Quit;



		public InputHandler(Game game)
			: base(game)
		{
			Game.Services.AddService(typeof(IInputEventService), this);
		}



		public override void Initialize()
		{
			base.Initialize();
		}



		public override void Update(GameTime gameTime)
		{
			KeyboardState currentKeyboardState = Keyboard.GetState();
			MouseState currentMouseState = Mouse.GetState();

			inputState.cameraPitchUp = currentKeyboardState.IsKeyDown(Keys.S);
			inputState.cameraPitchDown = currentKeyboardState.IsKeyDown(Keys.W);
			inputState.cameraRollLeft = currentKeyboardState.IsKeyDown(Keys.A);
			inputState.cameraRollRight = currentKeyboardState.IsKeyDown(Keys.D);
			inputState.cameraMoveForward = currentKeyboardState.IsKeyDown(Keys.PageUp);
			inputState.cameraMoveBackward = currentKeyboardState.IsKeyDown(Keys.PageDown);
			inputState.cameraYawLeft = currentKeyboardState.IsKeyDown(Keys.Q);
			inputState.cameraYawRight = currentKeyboardState.IsKeyDown(Keys.E);
			inputState.cameraMoveZForward = currentKeyboardState.IsKeyDown(Keys.O);
			inputState.cameraMoveZBackward = currentKeyboardState.IsKeyDown(Keys.L);
			inputState.playerMoveForward = currentKeyboardState.IsKeyDown(Keys.Up);
			inputState.playerMoveBackward = currentKeyboardState.IsKeyDown(Keys.Down);
			inputState.playerRotateLeft = currentKeyboardState.IsKeyDown(Keys.Left);
			inputState.playerRotateRight = currentKeyboardState.IsKeyDown(Keys.Right);
			inputState.playerShoot = currentKeyboardState.IsKeyDown(Keys.LeftControl);

			inputState.mouseLButtonPressed = (currentMouseState.LeftButton == ButtonState.Pressed) &&
												(previousMouseState.LeftButton == ButtonState.Released);
			inputState.mouseLButtonReleased = (currentMouseState.LeftButton == ButtonState.Released) &&
												(previousMouseState.LeftButton == ButtonState.Pressed);
			inputState.mouseRButtonPressed = (currentMouseState.RightButton == ButtonState.Pressed) &&
												(previousMouseState.RightButton == ButtonState.Released);
			inputState.mouseRButtonReleased = (currentMouseState.RightButton == ButtonState.Released) &&
												(previousMouseState.RightButton == ButtonState.Pressed);

			inputState.mouseX = currentMouseState.X;
			inputState.mouseY = currentMouseState.Y;

			if(currentKeyboardState.IsKeyDown(Keys.Escape))
			{
				if(Quit != null)
					Quit();
			}

			if(currentKeyboardState.IsKeyDown(Keys.H) && previousKeyboardState.IsKeyUp(Keys.H))
			{
				if(ToggleHUD != null)
					ToggleHUD();
			}

			previousKeyboardState = currentKeyboardState;
			previousMouseState = currentMouseState;

			base.Update(gameTime);
		}



		public static InputState GetState()
		{
			return inputState;
		}



		protected override void Dispose(bool disposing)
		{
			Game.Services.RemoveService(typeof(IInputEventService));
			base.Dispose(disposing);
		}
	}
}